package com.bolt.common.utils;

/**
 * Created by Administrator on 2020/7/1.
 */

import com.bolt.common.reflect.ObjectUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2020/6/29.
 */
@Slf4j
public class JacksonUtil {


    // 实例化ObjectMapper对象
    private static ObjectMapper objectMapper = new ObjectMapper();

    // 赋值
    static {
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(BigInteger.class, BigIntegerJsonDeserializer.getInstance());
        simpleModule.addSerializer(BigInteger.class, BigIntegerJsonSerializer.getInstance());
        objectMapper
                // 设置允许序列化空的实体类（否则会抛出异常）
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
                // 设置 把java.util.Date, Calendar输出为数字（时间戳）
                .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                // 设置在遇到未知属性的时候不抛出异常
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                // 强制JSON 空字符串("")转换为null对象值
                .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
                // 设置数字丢失精度问题
                .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
                // 设置没有引号的字段名
                .enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
                // 设置允许单引号
                .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES)
                // 设置接受只有一个元素的数组的反序列化
                .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
                .registerModule(simpleModule);
    }

    /**
     * 私有化构造器
     */
    private JacksonUtil() {
    }


    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    /**
     * 对象转json字符串
     *
     * @param obj
     * @return
     * @throws JsonProcessingException
     */
    public static String toJSONString(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException ex) {
            log.error(ex.getMessage(), ex);
            return null;
        }
    }


    public static JsonNode parseObj(String context) {
        try {
            return JacksonUtil.getObjectMapper().readTree(context);
        } catch (JsonProcessingException ex) {
            log.error(ex.getMessage(), ex);
            return null;
        }
    }



    /**
     * json字符串转换bean
     *
     * @param clazz
     * @param jsonStr
     * @return
     * @throws JsonProcessingException
     */
    public static <T> T parseObject(String jsonStr, Class<T> clazz) {
        try {

            return objectMapper.readValue(jsonStr, clazz);
        } catch (JsonProcessingException ex) {
            log.error(ex.getMessage(), ex);
            return null;
        }
    }

    /**
     * json字符串转Map
     *
     * @param jsonStr
     * @return
     */
    public static Map<String, Object> toMap(String jsonStr) {
        try {
            TypeReference<HashMap<String, Object>> typeRef
                    = new TypeReference<HashMap<String, Object>>() {
            };
            return objectMapper.readValue(jsonStr, typeRef);
        } catch (JsonProcessingException ex) {
            log.error(ex.getMessage(), ex);
            return null;
        }
    }

    public static Map<String, Object> toMap(JsonNode jsonNode) {
        Map<String, Object> data = objectMapper
                .convertValue(jsonNode, new TypeReference<Map<String, Object>>() {});
        return data;
    }

    public static boolean isJSON(String str) {
        return StrUtil.isBlank(str) ? false : StrUtil.isWrap(StrUtil.trim(str), '{', '}');
    }
    /**
     * json字符串转对象集合
     *
     * @param jsonStr
     * @param clazz
     * @param <T>
     * @return
     * @throws JsonProcessingException
     */
    public static <T> List<T> toList(String jsonStr, Class<T> clazz) {
        try {
            JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);
            return objectMapper.readValue(jsonStr, javaType);
        } catch (JsonProcessingException ex) {
            log.error(ex.getMessage(), ex);
            return null;
        }
    }

    public static final class BigIntegerJsonSerializer extends StdSerializer<BigInteger> {
        private static final BigIntegerJsonSerializer INSTANCE = new BigIntegerJsonSerializer();

        public static BigIntegerJsonSerializer getInstance() {
            return INSTANCE;
        }

        public BigIntegerJsonSerializer() {
            super(BigInteger.class);
        }

        @Override
        public void serialize(BigInteger bigInteger, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            if (ObjectUtil.isNotNull(bigInteger)) {
                jsonGenerator.writeString(bigInteger.toString());
            }
        }
    }

    public static final class BigIntegerJsonDeserializer extends StdDeserializer<BigInteger> {

        private static final BigIntegerJsonDeserializer INSTANCE = new BigIntegerJsonDeserializer();

        public static BigIntegerJsonDeserializer getInstance() {
            return INSTANCE;
        }

        public BigIntegerJsonDeserializer() {
            super(BigInteger.class);
        }

        @Override
        public BigInteger deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            if (jsonParser.hasToken(JsonToken.VALUE_STRING)) {
                String t1 = jsonParser.getText().trim();
                return new BigInteger(t1);
            } else {
                return null;
            }
        }
    }

}


 